package com.zheng.study.company.service.impl;

import cn.hutool.core.util.StrUtil;
import com.zheng.study.base.bean.BaseEnumManager;
import com.zheng.study.base.bean.Result;
import com.zheng.study.base.dao.BaseDao;
import com.zheng.study.base.service.impl.BaseServiceImpl;
import com.zheng.study.base.utils.HttpRequestUtil;
import com.zheng.study.company.dao.AdminDao;
import com.zheng.study.company.entity.Admin;
import com.zheng.study.company.entity.User;
import com.zheng.study.company.service.AdminService;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * newFile
 * ============================================================================
 * author : dzw
 * createDate:  2018/8/16 。
 * ============================================================================
 */
@Service
public class AdminServiceImpl extends BaseServiceImpl<Admin, String> implements AdminService {

	@Resource
	private AdminDao adminDao;

	public BaseDao<Admin, String> getBaseDao() {
		return adminDao;
	}

	public Admin createAdmin(BaseEnumManager.AccountEnum accountEnum, BaseEnumManager.AccountTypeEnum accountTypeEnum, String account, String password, Integer isEnabled) {
		// 检查账号类型是否有效
		if(accountEnum == null || !ArrayUtils.contains(Admin.ACCOUNT_PASSWORD, accountEnum)){
			return null;
		}

		// 创建 Admin 对象
		Admin admin = new Admin();
		if(BaseEnumManager.AccountEnum.USERNAME.equals(accountEnum)){
			admin.setUsername(account);
		}else if(BaseEnumManager.AccountEnum.MOBILE.equals(accountEnum)){
			admin.setUserMobile(account);
		}else if(BaseEnumManager.AccountEnum.MAIL.equals(accountEnum)){
			admin.setUserEmail(account);
		}
		admin.setAccountTypeEnum(accountTypeEnum);
		admin.setAccountEnum(accountEnum);
		admin.setAccountEnabled(isEnabled);
		admin.setHappy(password);
		admin.setSalt(new SecureRandomNumberGenerator().nextBytes().toHex());
		admin.setSecret(new SecureRandomNumberGenerator().nextBytes().toHex());
		save(admin);

		String encodePassword = encodedPassword(admin.getId(), password, admin.getSalt());
		admin.setPassword(encodePassword);
		update(admin);

		return admin;
	}

	public String encodedPassword(String uid, String password, String salt) {
		String algorithmName = "SHA-256";
		int hashIterations = 2;
		SimpleHash hash = new SimpleHash(algorithmName, password, uid + salt, hashIterations);
		return hash.toHex();
	}

	public Admin getAdminByAccount(String account) {
		return adminDao.getAdminByAccount(account);
	}

	public Admin getAdminByOpenId(String openId) {
		return adminDao.getAdminByOpenId(openId);
	}

	public Result updateOpenId(Admin admin, String openId) {
		if(StringUtils.isEmpty(openId)){
			clearOpenId(admin);
			return resultService.success();
		}

		Admin tempAdmin = getAdminByOpenId(openId);
		if(tempAdmin!=null){
			if(StringUtils.equals(admin.getOpenId(), tempAdmin.getOpenId())){
				return resultService.success();
			}else{
				clearOpenId(admin);
				setOpenId(admin, openId);
				return resultService.success();
			}
		}else{
			setOpenId(admin, openId);
			return resultService.success();
		}
	}

	@Override
	public String getAccount(Admin admin) {
		if(admin!=null){
			if(BaseEnumManager.AccountEnum.MOBILE.equals(admin.getAccountEnum())){
				return admin.getUserMobile();
			}else if(BaseEnumManager.AccountEnum.USERNAME.equals(admin.getAccountEnum())){
				return admin.getUsername();
			}else if(BaseEnumManager.AccountEnum.MAIL.equals(admin.getAccountEnum())){
				return admin.getUserEmail();
			}
		}
		return null;
	}

	@Override
	public String getAccount(User user) {
		if(user!=null){
			return getAccount(get(user.getAdminId()));
		}
		return null;
	}

	@Override
	public void updateLoginInfo(Admin admin, HttpServletRequest request) {
		if(admin!=null && request!=null){
			UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
			admin.setLoginDevice(userAgent.getBrowser().getName());
			admin.setLoginTime(new Date());
			admin.setLoginIp(HttpRequestUtil.getIpAddress(request));
			update(admin);
		}
	}

	@Override
	public Result updateUsername(Admin admin, String newUsername) {
		if(admin!=null && StrUtil.isNotBlank(newUsername)){
			if(getAdminByAccount(newUsername)==null){
				admin.setUsername(newUsername);
				update(admin);
				return resultService.successWithData(newUsername);
			}
		}
		return resultService.fail();
	}

	@Override
	public Result updateUserMobile(Admin admin, String newUserMobile) {
		if(admin!=null && StrUtil.isNotBlank(newUserMobile)){
			if(getAdminByAccount(newUserMobile)==null){
				admin.setUserMobile(newUserMobile);
				update(admin);
				return resultService.successWithData(newUserMobile);
			}
		}
		return resultService.fail();
	}

	@Override
	public Result updateUserEmail(Admin admin, String newUserEmail) {
		if(admin!=null && StrUtil.isNotBlank(newUserEmail)){
			if(getAdminByAccount(newUserEmail)==null){
				admin.setUserEmail(newUserEmail);
				update(admin);
				return resultService.successWithData(newUserEmail);
			}
		}
		return resultService.fail();
	}

	@Override
	public boolean validPassword(Admin admin, String password) {
		if(StrUtil.isNotBlank(password) && StrUtil.isNotBlank(admin.getSalt())){
			String encodedPassword = this.encodedPassword(admin.getId(), password, admin.getSalt());
			return StrUtil.equals(admin.getPassword(), encodedPassword);
		}
		return false;
	}

	@Override
	public Result updatePassword(Admin admin, String newPassword) {
		if(admin!=null && StrUtil.isNotBlank(newPassword)){
			admin.setSalt((new SecureRandomNumberGenerator()).nextBytes().toHex());
			admin.setSecret((new SecureRandomNumberGenerator()).nextBytes().toHex());
			String encodedPassword = this.encodedPassword(admin.getId(), newPassword, admin.getSalt());
			admin.setPassword(encodedPassword);
			this.update(admin);
			return resultService.success();
		}
		return resultService.fail();
	}

	//移除已绑定 OpenId
	public void clearOpenId(Admin admin) {
		if (StringUtils.isNotEmpty(admin.getOpenId())) {
			admin.setLastOpenId(admin.getOpenId());
		}
		admin.setOpenId(null);
		update(admin);
	}

	//绑定新openId
	public void setOpenId(Admin admin, String openId) {
		if (StringUtils.isNotEmpty(admin.getOpenId())) {
			admin.setLastOpenId(admin.getOpenId());
		}
		admin.setOpenId(openId);
		update(admin);
	}

}
